package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AuditService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;
	@Autowired
	private VodService vodService;
	@Autowired
	private AlbumInfoMapper albumInfoMapper;
	@Autowired
	private TrackStatMapper trackStatMapper;
	@Autowired
	private AuditService auditService;
	@Autowired
	private UserFeignClient userFeignClient;
	@Autowired
	private AlbumStatMapper albumStatMapper;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveTrackInfo(TrackInfoVo trackInfoVo) {
		//获取所属专辑id,得到封面图片,用于后续更新
		Long albumId = trackInfoVo.getAlbumId();
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		if(albumInfo == null){
			log.error("专辑:{}不存在",albumId);
			throw new GuiguException(404,"专辑不存在");
		}

		//新增声音记录
		//创建实例对象
		TrackInfo trackInfo = new TrackInfo();
		//封装属性
		BeanUtils.copyProperties(trackInfoVo,trackInfo);
		//获取用户id
		Long userId = AuthContextHolder.getUserId();
		trackInfo.setUserId(userId);
		//获取声音在专辑中的排序值
		trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
		trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);//用户原创
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
		//如果未提交封面图片,则使用所属专辑封面
		if(StringUtils.isBlank(trackInfoVo.getCoverUrl())){
			trackInfo.setCoverUrl(albumInfo.getCoverUrl());
		}

		//调用点播平台获取音频详情信息:时长、大小、类型
		TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(trackInfoVo.getMediaFileId());
		if(trackMediaInfo != null){
			trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfo.getDuration()));
			trackInfo.setMediaSize(trackMediaInfo.getSize());
			trackInfo.setMediaType(trackMediaInfo.getType());
		}
		//插入声音记录
		trackInfoMapper.insert(trackInfo);
		//回显声音id
		Long trackInfoId = trackInfo.getId();

		//更新专辑信息
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() +1);
		albumInfoMapper.updateById(albumInfo);

		//插入声音统计记录
		saveTrackStat(trackInfoId,SystemConstant.TRACK_STAT_PLAY,0);
		saveTrackStat(trackInfoId,SystemConstant.TRACK_STAT_COLLECT,0);
		saveTrackStat(trackInfoId,SystemConstant.TRACK_STAT_PRAISE,0);
		saveTrackStat(trackInfoId,SystemConstant.TRACK_STAT_COMMENT,0);

		// 内容审核-文本审核
		String content = trackInfo.getTrackTitle() + trackInfo.getTrackIntro();
		String auditTextResult = auditService.auditText(content);
		if("pass".equals(auditTextResult)){
			trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
		}else if("review".equals(auditTextResult)){
			trackInfo.setStatus(SystemConstant.TRACK_STATUS_REVIEW);
		}else if("block".equals(auditTextResult)){
			trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
		}
		// 对点播平台音频文件进行审核(异步审核)
		String reviewTaskId = auditService.startReviewTask(trackInfo.getMediaFileId());
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_REVIEW);
		trackInfo.setReviewTaskId(reviewTaskId);
		trackInfoMapper.updateById(trackInfo);

	}

	@Override
	public Page<TrackListVo> findUserTrackPage(Page<TrackListVo> trackInfoPage, TrackInfoQuery voQuery) {
		Page<TrackListVo> result = trackInfoMapper.findUserTrackPage(trackInfoPage,voQuery);

		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateTrackInfo(TrackInfo trackInfo) {
		//获取旧的声音数据
		Long trackInfoId = trackInfo.getId();
		TrackInfo oldTrackInfo = trackInfoMapper.selectById(trackInfoId);

		//对修改后的文本内容进行审核
		String content = trackInfo.getTrackTitle() + trackInfo.getTrackIntro();
		String auditTextResult = auditService.auditText(content);
		if("pass".equals(auditTextResult)){
			trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
		}else if("review".equals(auditTextResult)){
			trackInfo.setStatus(SystemConstant.TRACK_STATUS_REVIEW);
		}else if("block".equals(auditTextResult)){
			trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
		}

		//比较新旧音频是否一致,如果一样则不用更新
		//通过音频的唯一标识进行比较
		if(!oldTrackInfo.getMediaFileId().equals(trackInfo.getMediaFileId())){
			//重新获取媒体资源数据
			TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(trackInfo.getMediaFileId());
			if(trackMediaInfo!=null){
				trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfo.getDuration()));
				trackInfo.setMediaType(trackMediaInfo.getType());
				trackInfo.setMediaSize(trackMediaInfo.getSize());
			}
			//从点播平台删除旧的音频文件
			vodService.deleteMedia(oldTrackInfo.getMediaFileId());
			//对新的音频数据进行审核
			String reviewTaskId = auditService.startReviewTask(trackInfo.getMediaFileId());
			trackInfo.setStatus(SystemConstant.TRACK_STATUS_REVIEW); //修改音频数据审核状态
			trackInfo.setReviewTaskId(reviewTaskId);
		}
		//更新数据
		trackInfoMapper.updateById(trackInfo);
	}

	@Override
	public void removeTrackInfo(Long id) {
		TrackInfo trackInfo = trackInfoMapper.selectById(id);
		if(trackInfo == null){
			return;
		}
		//修改专辑中的声音表序号
		Long albumId = trackInfo.getAlbumId();
		Integer orderNum = trackInfo.getOrderNum();
		LambdaUpdateWrapper<TrackInfo> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.eq(TrackInfo::getAlbumId,albumId)
				.gt(TrackInfo::getOrderNum,orderNum)
						.setSql("order_num = order_num - 1");
		//更新声音序号-确保连续
		trackInfoMapper.update(null,updateWrapper);

		//删除主数据
		trackInfoMapper.deleteById(id);
		//删除附属状态数据
		trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>()
				.eq(TrackStat::getTrackId,id));
		//更新专辑中包含声音数量
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
		albumInfoMapper.updateById(albumInfo);

		//删除点播平台音频文件
		vodService.deleteMedia(trackInfo.getMediaFileId());

	}

	@Override
	public void saveTrackStat(Long trackId, String statType, int statNum){
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(trackId);
		trackStat.setStatType(statType);
		trackStat.setStatNum(statNum);
		trackStat.setCreateTime(DateUtil.date());

		trackStatMapper.insert(trackStat);
	}

    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(IPage<AlbumTrackListVo> pageInfo, Long albumId) {
		IPage<AlbumTrackListVo> result = trackInfoMapper.findAlbumTrackPage(pageInfo,albumId);

		//根据专辑id获取此专辑中的付费类型和免费试听集数
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		//付费类型: 0101-免费、0102-vip免费、0103-付费
		String payType = albumInfo.getPayType();
		Integer tracksForFree = albumInfo.getTracksForFree();

		//判断用户是否登录
		Long userId = AuthContextHolder.getUserId();
		if(userId == null){
			//如果没登录,且专辑不是免费
			if(SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType) || SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)){
				//除了试听之外的,都需要加上付费标记
				result.getRecords().stream()
						.filter(f->f.getOrderNum() >tracksForFree)
						.forEach(f->f.setIsShowPaidMark(true));
			}
		}else{
			//如果登录
			UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(userId).getData();
			Assert.notNull(userInfoVo,"用户id:{}不存在",userId);
			Boolean isVIP = false;
			//判断用户是否是vip且没有过期
			if(userInfoVo.getIsVip().intValue() == 1 && userInfoVo.getVipExpireTime().after(new Date())){
				isVIP = true;
			}
			//如果专辑为付费类型,则需进一步查询当前页声音购买状态
			Boolean isNeedCheckPayStatus = false;
			if(SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)){
				isNeedCheckPayStatus = true;
			}
			//如果专辑为vip免费,且当前用户为普通用户,则进一步查询用户是否单独购买此页声音
			if(SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType) && !isVIP){
				isNeedCheckPayStatus = true;
			}
			//如果需要进一步进行判断
			if(isNeedCheckPayStatus){
				//获取此页除试听外的其他声音ID列表
				List<Long> needCheckPayStatusTrackIdList = result.getRecords().stream()
						.filter(t -> t.getOrderNum() > tracksForFree)
						.map(AlbumTrackListVo::getTrackId)
						.collect(Collectors.toList());

				//调用远程服务
				Map<Long, Integer> payStatusMap = userFeignClient.userIsPaidTrack(userId, albumId, needCheckPayStatusTrackIdList).getData();
				//根据表示设置付费表示
				result.getRecords().stream()
						.filter(f -> f.getOrderNum() > tracksForFree)
						.forEach(f -> f.setIsShowPaidMark(payStatusMap.get(f.getTrackId())==0));
				return result;
			}
		}
		return result;
    }

	/**
	 * 查询声音统计信息
	 * @param trackId
	 * @return
	 */
	@Override
	public TrackStatVo getTrackStatVo(Long trackId) {
//		TrackStatVo trackStatVo = trackStatMapper.selectTrackStatVoById(trackId);
		TrackStatVo trackStatVo = trackInfoMapper.selectTrackStatVoById(trackId);
		return trackStatVo;
	}

	/**
	 * 更新DB中声音/专辑统计数值
	 *
	 * @param Vo
	 */
	@Override
	public void updateTrackStat(TrackStatMqVo vo) {
		//更新声音统计数值
		trackStatMapper.update(
				null,
				new LambdaUpdateWrapper<TrackStat>()
						.eq(TrackStat::getTrackId,vo.getTrackId())
						.eq(TrackStat::getStatType, vo.getStatType())
						.setSql("stat_num = stat_num + " + vo.getCount())
		);

		//如果是播放或评论则还需要同步更新专辑的统计数目
		if(SystemConstant.TRACK_STAT_PLAY.equals(vo.getStatType())){
			albumStatMapper.update(
					null,
					new LambdaUpdateWrapper<AlbumStat>()
							.eq(AlbumStat::getAlbumId, vo.getAlbumId())
							.eq(AlbumStat::getStatType, SystemConstant.ALBUM_STAT_PLAY)
							.setSql("stat_num = stat_num + " + vo.getCount())
			);
		}

		if(SystemConstant.TRACK_STAT_COMMENT.equals(vo.getStatType())){
			albumStatMapper.update(
					null,
					new LambdaUpdateWrapper<AlbumStat>()
							.eq(AlbumStat::getAlbumId, vo.getAlbumId())
							.eq(AlbumStat::getStatType, SystemConstant.ALBUM_STAT_COMMENT)
							.setSql("stat_num = stat_num + " + vo.getCount())
			);
		}
	}

	/**
	 *  查询用户未购买声音列表
	 * @param trackId 选择购买声音ID，作为起始标准计算未购买声音数量
	 * @param trackCount 限制查询未购买声音数量
	 * @return
	 */
	@Override
	public List<TrackInfo> findPaidTrackInfoList(Long userId, Long trackId, Integer trackCount) {
		//根据声音id获取到专辑信息
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		Long albumId = trackInfo.getAlbumId();
		Integer orderNum = trackInfo.getOrderNum();
		
		//远程调用查看当前用户在当前专辑中已购买的声音列表
		List<Long> userPaidTrackList = userFeignClient.findUserPaidTrackList(albumId).getData();

		//构建条件查询未购买声音列表
		LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<TrackInfo>()
				.eq(TrackInfo::getAlbumId,albumId)
				.ge(TrackInfo::getOrderNum,orderNum)
				.orderByAsc(TrackInfo::getOrderNum)
				.select(TrackInfo::getId,TrackInfo::getTrackTitle,TrackInfo::getCoverUrl,TrackInfo::getAlbumId)
				.last("limit " + trackCount);
		if(!CollectionUtils.isEmpty(userPaidTrackList)){
			queryWrapper.notIn(TrackInfo::getId,userPaidTrackList);
		}

		List<TrackInfo> trackInfoList = trackInfoMapper.selectList(queryWrapper);
		return trackInfoList;
	}


}
